package me.kuye.jkuye.render;

import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import javax.servlet.ServletContext;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;

public class VelocityRender extends Render {

	private static final String encoding = getEncoding();
	private static final String contentType = "text/html; charset=" + encoding;
	private static final Properties properties = new Properties();

	private static boolean notInit = true;

	public VelocityRender(String view) {
		this.view = view;
	}

	@Override
	public void render() {
		if (notInit) {
			Velocity.init(properties);
			notInit = false;
		}

		PrintWriter out = null;
		try {
			VelocityContext velocityContext = new VelocityContext();

			for (Enumeration<String> attrs = request.getAttributeNames(); attrs.hasMoreElements();) {
				String attrName = attrs.nextElement();
				velocityContext.put(attrName, request.getAttribute(attrName));
			}
			Template template = Velocity.getTemplate(view);
			response.setContentType(contentType);
			out = response.getWriter();
			template.merge(velocityContext, out);
			out.flush();
		} catch (ResourceNotFoundException e) {
			throw new RenderException("Example : error : cannot find template " + view, e);
		} catch (ParseErrorException e) {
			throw new RenderException("Example : Syntax error in template " + view + ":" + e, e);
		} catch (Exception e) {
			throw new RenderException(e);
		} finally {
			if (out != null)
				out.close();
		}
	}

	public static void init(ServletContext servletContext) {
		String webPath = servletContext.getRealPath("/");
		properties.put(Velocity.FILE_RESOURCE_LOADER_CACHE, webPath);
		properties.put(Velocity.ENCODING_DEFAULT, encoding);
		properties.setProperty(Velocity.INPUT_ENCODING, encoding);
		properties.setProperty(Velocity.OUTPUT_ENCODING, encoding);
	}

	public static void setProperties(Properties properties) {
		Set<Entry<Object, Object>> set = properties.entrySet();
		for (Iterator<Entry<Object, Object>> it = set.iterator(); it.hasNext();) {
			Entry<Object, Object> entry = it.next();
			VelocityRender.properties.put(entry.getKey(), entry.getValue());
		}
	}

}
